package com.wyg.lambda.streamapi.create;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Stream API Demo
 *
 * 一、Stream 创建
 *      1.通过数组      Stream.of(Array);
 *      2.通过集合      list.stream();
 *      3.通过Stream.generate方法来创建 Stream.generate(Supplier<T> s);
 *      4.通过Stream.iterate方法来创建  Stream.iterate(T seed,UnaryOperator<T> f);
 *      5.其他API创建
 *              int流：
 *                  String str = "abcdefg";
 *                  IntStream intStream = str.chars();
 *              文件流：
 *                  Stream<String> stream = Files.lines();
 *
 *
 * forEach遍历解析：
 *
 *      //1. void forEach(IntConsumer action);
 *      //2. public interface IntConsumer ->  void accept(int value)
 *
 *      intStream.forEach(new IntConsumer() {
 *             @Override
 *             public void accept(int value) {
 *                 System.out.println(value);
 *             }
 *      });
 *      //改进Lambda表达式
 *      intStream.forEach(x -> System.out.println(x));
 *      intStream.forEach(System.out::println);
 *
 * @ClassName: StreamCreate
 * @Auther: WangYG
 * @Date: 2020-02-22 16:33:40
 * @Version: 1.0
 */
public class StreamCreate {

    /**
     * 功能描述: 1.通过数组创建Stream
     *
     * public static<T> Stream<T> of(T... values)
     * public static<T> Stream<T> of(T t)
     *
     * @methodName: one
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 17:04:12
     */
    public void one(){
        Integer[] intArray = {1,2,3,4,5,6,7,8};
        String[] strArray = {"张三","李四","王五","赵六","燕七"};
        Double[] doubleArray = {1D,2D,3D,4D,5D,6D};
        Stream<Integer> intStream = Stream.of(intArray);
        Stream<String> strStream = Stream.of(strArray);
        Stream<Double> doubleStream = Stream.of(doubleArray);
        //遍历输出
        intStream.forEach(x -> System.out.println("Stream 创建方式之Stream.of(Array)数组创建 intStream ：" + x));
        strStream.forEach(x -> System.out.println("Stream 创建方式之Stream.of(Array)数组创建 strStream ：" + x));
        doubleStream.forEach(System.out::println);
    }

    /**
     * 功能描述: 2.通过集合创建
     *
     * list.stream();
     *
     * @methodName: two
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 17:08:26
     */
    public void two(){

        String[] strArray = {"张三","李四","王五","赵六","燕七"};
        List<String> list = Arrays.asList(strArray);
        Stream<String> strStream = list.stream();

        Integer[] intArray = {1,2,3,4,5,6,7,8};
        List<Integer> intList = Arrays.asList(intArray);
        Stream<Integer> intStream = intList.stream();
        //遍历解析
        strStream.forEach(x -> System.out.println("Stream 创建方式之list.stream集合创建 strStream ：" + x));
        intStream.forEach(x -> System.out.println("Stream 创建方式之list.stream集合创建 intStream ：" + x));
    }

    /**
     * 功能描述: 3.通过Stream.generate方法来创建
     *
     * public static<T> Stream<T> generate(Supplier<T> s){}
     *      ---- public interface Supplier<T> {T get();}
     *
     * @methodName: three
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 17:17:29
     */
    public void three(){

        //1.使用匿名内部类方式创建
        Stream<Integer> stream1 = Stream.generate(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return 111;
            }
        });

        //2.使用Lambda表达式创建
        Stream<Integer> stream2 = Stream.generate(() -> {return 222;});

        //3.使用Lambda表达式-省略返回部分 创建
        Stream<Integer> stream3 = Stream.generate(() -> 333);

        //遍历解析
        // 单元素时？stream1.forEach会一直执行Supplier<T> s类的方法，生成一个无止境的循环流。
        // 解决办法：使用截取操作方法防止无限循环，如:limit(),skip()等；

        //下面这个没有使用截取操作方法，会无限循环。
        //stream1.forEach(x -> System.out.println("Stream 创建方式之Stream.generate(Supplier<T> s) generate创建 stream1 ：" + x));

        //使用limit方法-防止forEach死循环
        stream1.limit(1).forEach(x -> System.out.println("Stream 创建方式之Stream.generate(Supplier<T> s) generate创建 stream1 ：" + x));
        stream2.limit(2).forEach(x -> System.out.println("Stream 创建方式之Stream.generate(Supplier<T> s) generate创建 stream2 ：" + x));
        stream3.limit(3).forEach(x -> System.out.println("Stream 创建方式之Stream.generate(Supplier<T> s) generate创建 stream3 ：" + x));

    }

    /**
     * 功能描述: 4.通过Stream.iterate方法来创建
     *
     *  关键因素：iterate(T seed, UnaryOperator<T> f) 入参T类型前后必须一致。
     *
     *  public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {}
     *
     *      ----public interface UnaryOperator<T> extends Function<T, T>
     *          UnaryOperator<T> f 一个入参，一个出参(入参和出参必须为同一类型)。
     *
     *  解析：
     *      Stream.iterate(T seed,UnaryOperator<T> f)
     *          UnaryOperator<T> f ：类型和值取决于第一个参数-> T seed
     *
     *  特点：单元素时？ 会将UnaryOperator<T> f的执行结果，再次当成新的参数传入，继续循环。
     *  解决方法：使用limit、skip等方法防止无限循环。
     *
     * @methodName: four
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 17:38:24
     */
    public void four(){
        Integer num = 1;
        String code = "LAMBDA";

        //1.使用普通匿名内部类方式创建
        Stream<Integer> stream1 = Stream.iterate(num, new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return ++integer;
            }
        });
        //Stream.iterate创建 -> 传入Lambda表达式
        Stream<Integer> stream2 = Stream.iterate(num, (Integer m) -> {return ++m;});
        Stream<Integer> stream3 = Stream.iterate(num, m -> ++m);


        //2.Stream.iterate创建 -> 传入Lambda表达式
        Stream<String> stream4 = Stream.iterate(code, (String name) -> {
            return name.toLowerCase();
        });

        //3.Lambda表示式-简写省略
        Stream<String> stream5 = Stream.iterate(code, name -> name.toLowerCase());

        //4.Lambda-表达式-方法引用
        Stream<String> stream6 = Stream.iterate(code, String::toLowerCase);

        //使用limit()方法防止无限循环遍历解析
        stream1.limit(1).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 Integer stream1 ：" + x));
        stream2.limit(2).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 Integer stream2 ：" + x));
        stream3.limit(3).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 Integer stream3 ：" + x));
        stream4.limit(1).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 String stream4 ：" + x));
        stream5.limit(2).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 String stream5 ：" + x));
        stream6.limit(3).forEach(x -> System.out.println("Stream 创建方式之Stream.iterate创建 String stream6 ：" + x));

    }

    /**
     * 功能描述: 其它方式创建Stream
     *
     * String str = "abcdefg";
     * IntStream intStream = str.chars();
     *
     * forEach遍历解析：
     *
     *      //1. void forEach(IntConsumer action);
     *      //2. public interface IntConsumer ->  void accept(int value)
     *
     *      intStream.forEach(new IntConsumer() {
     *             @Override
     *             public void accept(int value) {
     *                 System.out.println(value);
     *             }
     *      });
     *      //改进Lambda表达式
     *      intStream.forEach(x -> System.out.println(x));
     *
     * @methodName: five
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 17:57:37
     */
    public void five(){

        String str = "abcdefg";
        //其它方式创建Stream
        //intStream.forEach之后，就不可以再次使用了，所以这个创建多个IntStream 1,2,3.
        IntStream intStream1 = str.chars(),
                intStream2 = str.chars(),
                intStream3 = str.chars();

        //1. void forEach(IntConsumer action);
        //2. public interface IntConsumer ->  void accept(int value)
        intStream1.forEach(new IntConsumer() {
            @Override
            public void accept(int value) {
                System.out.println("Stream 创建方式之其它API创建  intStream1.forEach accept() value is : " + value);
            }
        });
        //IntConsumer中accept(int value){...}
        intStream2.forEach(x -> System.out.println("Stream 创建方式之其它API创建  intStream2.forEach accept() x is : " + x));
        //Lambda表达式-方法引用方式
        intStream3.forEach(System.out::println);

        //Stream遍历演示 - 字符串
        String[] strArray = {"张三","李四","王五","赵六","燕七"};
        Stream<String> strStream1 = Stream.of(strArray),
                strStream2 = Stream.of(strArray),
                strStream3 = Stream.of(strArray);

        strStream1.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("Stream 创建方式之其它API创建  strStream1.forEach accept() s is : " + s);
            }
        });

        //遍历解析
        strStream2.forEach(code -> System.out.println("Stream 创建方式之其它API创建  strStream2.forEach accept() code is : " + code));

        strStream3.forEach(System.out::println);

    }

    /**
     * 功能描述: 其它API方式创建Stream
     *
     * Stream<String> stream = Files.lines();
     *
     * @methodName: six
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-22 18:25:41
     */
    public void six() throws IOException {

        //File file = new File(resources/properties/basecom.properties");

        String pathStr = this.getClass().getPackage().getName();
        pathStr = "src/main/java/" + pathStr.replace(".","/") + "/readTest.txt";
        //System.out.println(pathStr);
        Stream<String> fileLinesStream = Files.lines(Paths.get(pathStr), Charset.forName("UTF-8"));
        Stream<String> fileLinesStream2 = Files.lines(Paths.get(pathStr), Charset.forName("UTF-8"));
        //遍历解析
        fileLinesStream.forEach(x -> System.out.println("Stream 创建方式之其它API创建 fileLinesStream ：" + x));
        fileLinesStream2.forEach(System.out::println);
    }

}
